package com.xiye.zuul.filter;

import javax.servlet.http.HttpServletRequest;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.xiye.common.entity.User;
import com.xiye.common.util.Const;
import com.xiye.common.util.Jurisdiction;
import com.xiye.common.util.ResultUtil;
import org.springframework.beans.factory.annotation.Value;

import java.util.HashMap;
import java.util.Map;

/**
 * @author 西野
 * @version V1.0
 * @title AccessUserFilter.java
 * @package com.xiye.zuul.filter
 * @description 登录验证，由shiro管理session
 * @date 2018-06-21
 */
public class AccessUserFilter extends ZuulFilter {

    /*
     * @Author 西野
     * @Date 2018-07-13 15:36:09
     * @Description 路由名称，配置在远程服务中心，用以拦截请求时去掉路由名称，以便于匹配菜单权限
     * @Param
     * @Return
     */
    @Value("${xiye.routes}")
    private String routes;

    /*
     * @Author 西野
     * @Date 2018-06-21 14:06:06
     * @Description 过滤器类型，执行顺序: pre ->routing -> post ,以上3个顺序出现异常时都可以触发error类型的filter
     *              pre：可以在请求被路由之前调用;routing:路由请求时被调用;post:在routing和error过滤器之后被调用
     * @Param []
     * @Return java.lang.String
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /*
     * @Author 西野
     * @Date 2018-06-21 14:06:06
     * @Description 是否应该执行该过滤器，如果是false，则不执行该filter
     * @Param []
     * @Return boolean
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /*
     * @Author 西野
     * @Date 2018-06-21 14:06:06
     * @Description 同filterType类型中，order值越大，优先级越低
     * @Param []
     * @Return int
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        Map<String, Object> map = new HashMap<String, Object>();
        String path = request.getServletPath();//请求地址
        try {
            //TODO 临时在Const.NO_INTERCEPTOR_PATH添加忽略xiye-system/v2/api-docs接口文档请求，留待后续处理，对于不拦截的请求，不做返回处理。
            if (path.matches(Const.NO_INTERCEPTOR_PATH)) {
                ctx.setSendZuulResponse(true);// 对该请求进行路由
                ctx.setResponseStatusCode(200);
                ctx.set("success", true);// 设值，让下一个Filter看到上一个Filter的状态
            } else {
                User user = Jurisdiction.getUser(Const.SESSION_USER); // 读取session中的用户信息(单独用户信息)
                /*
                 * 获取配置中心中定义的路由名称配置
                 * 并将请求地址中路由名称替换掉
                 * 菜单权限数据库表中不存子服务的路由名称，只存路由之后的字符
                 */
                String[] routeArray = routes.split(",");
                for (int i = 0; i < routeArray.length; i++) {
                    path = path.replace(routeArray[i], "");
                }
                if (user != null && !path.isEmpty()) {
                    path = path.substring(1, path.length());
                    boolean b = Jurisdiction.hasJurisdiction(path); // 访问权限校验
                    if (!b) {
                        ctx.setSendZuulResponse(false);// 过滤该请求，不对其进行路由
                        ctx.setResponseStatusCode(403);// 返回错误码
                        //ctx.setResponseBody("{\"result\":\"请先登录!\"}");// 返回错误内容
                        ctx.set("success", false);
                        return ResultUtil.setRowbackResut_entity(false, 403, "您没有操作该功能的权限!", map);
                    } else {
                        /*符合路由成功条件的不必加返回，返回在子项目的请求方法里写，否则会产生异常*/
                        ctx.setSendZuulResponse(true);// 对该请求进行路由
                        /*ctx.setResponseStatusCode(200);*/
                        ctx.set("success", true);// 设值，让下一个Filter看到上一个Filter的状态
                    }
                } else {
                    // 登陆过滤
                    ctx.setSendZuulResponse(false);// 过滤该请求，不对其进行路由
                    ctx.setResponseStatusCode(401);// 返回错误码
                    //ctx.setResponseBody("{\"result\":\"请先登录!\"}");// 返回错误内容
                    ctx.set("success", false);
                    return ResultUtil.setRowbackResut_entity(false, 401, "请您先登录!", map);
                }
            }
        } catch (Exception e) {
            //logger.error(e.toString(), e);
            e.printStackTrace();
        }
        return null;
    }
}
